package com.xy.service.calculate.maori;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xy.api.exception.BizException;
import com.xy.api.model.dto.calculate.maori.MaoriProductDTO;
import com.xy.api.model.dto.calculate.maori.MaoriProductInstanceDTO;
import com.xy.api.model.request.calculate.maori.MaoriProductRequest;
import com.xy.api.model.response.Rows;
import com.xy.api.service.calculate.maori.IMaoriProductService;
import com.xy.mapper.calculate.maori.MaoriProductInstanceMapper;
import com.xy.mapper.calculate.maori.MaoriProductMapper;
import com.xy.mapper.mainData.ProductInstanceMapper;
import com.xy.mapper.mainData.ProductMapper;
import com.xy.model.condition.costing.CostingProductCondition;
import com.xy.model.condition.costing.CostingProductInstanceCondition;
import com.xy.model.po.calculate.maori.MaoriProductInstancePO;
import com.xy.model.po.calculate.maori.MaoriProductPO;
import com.xy.model.po.mainData.ProductInstancePO;
import com.xy.model.po.mainData.ProductPO;
import com.xy.utils.CustomBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MaoriProductServiceImpl implements IMaoriProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductInstanceMapper productInstanceMapper;

    @Autowired
    private MaoriProductMapper maoriProductMapper;

    @Autowired
    private MaoriProductInstanceMapper maoriProductInstanceMapper;

    @Override
    public Rows<MaoriProductDTO> queryProductList(MaoriProductRequest request) {
        Rows<MaoriProductDTO> result = new Rows<>();
        CostingProductCondition condition = new CostingProductCondition();
        condition.setName(request.getName());
        int total = maoriProductMapper.count(condition);
        result.setTotal(total);
        if (total > 0) {
            Integer pageSize = null != request.getPageSize() ? request.getPageSize() : 10;
            Integer pageNum = null != request.getPageNum() ? request.getPageNum() : 1;
            Integer pageStart = (pageNum - 1) * pageSize;
            condition.setPageSize(pageSize);
            condition.setPageStart(pageStart);
            List<MaoriProductPO> costingProductPOList = maoriProductMapper.queryList(condition);
            List<MaoriProductDTO> list = CustomBeanUtil.copyListProperties(costingProductPOList, MaoriProductDTO::new);
            result.setRows(list);

            List<Long> costingProductIdList = costingProductPOList.stream().map(e -> e.getId()).collect(Collectors.toList());
            CostingProductInstanceCondition instanceCondition = new CostingProductInstanceCondition();
            instanceCondition.setCostingProductIdList(costingProductIdList);
            instanceCondition.setIsTotal(1);
            List<MaoriProductInstancePO> costingProductInstancePOS = maoriProductInstanceMapper.queryList(instanceCondition);
            if (!CollectionUtils.isEmpty(costingProductInstancePOS)) {
                List<MaoriProductInstanceDTO> instanceList = CustomBeanUtil.copyListProperties(costingProductInstancePOS, MaoriProductInstanceDTO::new);
                Map<Long, MaoriProductInstanceDTO> instanceMap = instanceList.stream().filter(e -> Objects.equals(e.getIsTotal(), 1)).collect(Collectors.toMap(e -> e.getCostingProductId(), e -> e, (e1, e2) -> e2));

                for (MaoriProductDTO costingProduct : list) {
                    Long id = costingProduct.getId();
                    MaoriProductInstanceDTO totalInstance = instanceMap.get(id);
                    costingProduct.setTotalInstance(totalInstance);
                }
            }
        }
        return result;
    }

    @Override
    public void editProduct(MaoriProductDTO request) {
        Assert.hasText(request.getName(), "项目名称必填");

        if (null != request.getProductId()) {
            ProductPO existProduct = productMapper.selectById(request.getProductId());
            if (null == existProduct) {
                throw new BizException("产品不存在");
            }
            request.setProductName(existProduct.getName());
            request.setPlOne(existProduct.getPlOne());
            request.setPlTwo(existProduct.getPlTwo());
            request.setVariantCodeOne(existProduct.getVariantCodeOne());
            request.setVariantCodeTwo(existProduct.getVariantCodeTwo());
            request.setProductUnit(existProduct.getProductUnit());
            request.setWeightUnit(existProduct.getWeightUnit());
        }
        if (null != request.getId()) {
            updateProduct(request);
            if (null == request.getProductId()) {
                maoriProductMapper.clearProductId(request.getId());
            } else {
                updateMaoriProductInstanceByProductId(request.getProductId(), request.getId());
            }
        } else {
            MaoriProductPO insertMaoriProductPO = addProduct(request);
            if (null != request.getProductId()) {
                addMaoriProductInstanceByProductId(request.getProductId(), insertMaoriProductPO.getId());
            }
        }
    }

    private MaoriProductPO addProduct(MaoriProductDTO product) {
        MaoriProductPO record = new MaoriProductPO();
        CustomBeanUtil.copyProperties(product, record);
        maoriProductMapper.insert(record);
        return record;
    }

    private void updateProduct(MaoriProductDTO product) {
        Assert.notNull(product.getId(), "id必填");
        MaoriProductPO record = new MaoriProductPO();
        CustomBeanUtil.copyProperties(product, record);
        maoriProductMapper.updateById(record);
    }

    /**
     * 根据产品更新成本核算实例
     *
     * @param productId
     * @param maoriProductId
     */
    private void updateMaoriProductInstanceByProductId(Long productId, Long maoriProductId) {
        MaoriProductPO existMaoriProductPO = maoriProductMapper.selectById(maoriProductId);
        if (Objects.equals(existMaoriProductPO.getProductId(), productId)) {
            return;
        }
        LambdaQueryWrapper<MaoriProductInstancePO> deleteMaoriProductInstanceWrapper = new LambdaQueryWrapper<>();
        deleteMaoriProductInstanceWrapper.eq(MaoriProductInstancePO::getCostingProductId, maoriProductId);
        MaoriProductInstancePO deleteMaoriProductInstanceRecord = new MaoriProductInstancePO();
        deleteMaoriProductInstanceRecord.setIsDeleted(1);
        maoriProductInstanceMapper.update(deleteMaoriProductInstanceRecord, deleteMaoriProductInstanceWrapper);

        addMaoriProductInstanceByProductId(productId, maoriProductId);
    }

    /**
     * 更具产品构建核算实例
     *
     * @param productId
     * @param maoriProductId
     */
    private void addMaoriProductInstanceByProductId(Long productId, Long maoriProductId) {
        Assert.notNull(productId, "产品ID必填");
        LambdaQueryWrapper<ProductInstancePO> productInstanceWrapper = new LambdaQueryWrapper<>();
        productInstanceWrapper
                .eq(ProductInstancePO::getIsDeleted, false)
                .eq(ProductInstancePO::getProductId, productId);
        List<ProductInstancePO> productInstancePOS = productInstanceMapper.selectList(productInstanceWrapper);
        if (!CollectionUtils.isEmpty(productInstancePOS)) {

            for (ProductInstancePO productInstancePO : productInstancePOS) {
                MaoriProductInstancePO insertMaoriProductInstanceRecord = new MaoriProductInstancePO();
                insertMaoriProductInstanceRecord.setCostingProductId(maoriProductId);
                insertMaoriProductInstanceRecord.setIsTotal(0);
                insertMaoriProductInstanceRecord.setVariantCodeOneValue(productInstancePO.getVariantCodeOneValue());
                insertMaoriProductInstanceRecord.setVariantCodeTwoValue(productInstancePO.getVariantCodeTwoValue());
                insertMaoriProductInstanceRecord.setProductLength(productInstancePO.getProductLength());
                insertMaoriProductInstanceRecord.setProductWidth(productInstancePO.getProductWidth());
                insertMaoriProductInstanceRecord.setProductHeight(productInstancePO.getProductHeight());
                insertMaoriProductInstanceRecord.setPacketLength(productInstancePO.getPacketLength());
                insertMaoriProductInstanceRecord.setPacketWidth(productInstancePO.getPacketWidth());
                insertMaoriProductInstanceRecord.setPacketHeight(productInstancePO.getPacketHeight());
                insertMaoriProductInstanceRecord.setOuterCartonPackCount(productInstancePO.getOuterCartonPackCount());
                insertMaoriProductInstanceRecord.setProductWeight(productInstancePO.getProductWeight());
                insertMaoriProductInstanceRecord.setPackageWeight(productInstancePO.getPackageWeight());
                insertMaoriProductInstanceRecord.setPacketTrueWeight(productInstancePO.getPacketTrueWeight());

                maoriProductInstanceMapper.insert(insertMaoriProductInstanceRecord);
            }
        }
    }

    @Override
    public void deleteProduct(MaoriProductDTO request) {
        Assert.notNull(request.getId(), "项目id必填");
        maoriProductMapper.delete(request.getId());
    }

    @Override
    public MaoriProductDTO productDetail(MaoriProductDTO request) {
        Assert.notNull(request.getId(), "项目id必填");
        MaoriProductPO productPO = maoriProductMapper.selectById(request.getId());
        if (null == productPO) {
            throw new BizException("项目不存在");
        }
        MaoriProductDTO result = new MaoriProductDTO();
        CustomBeanUtil.copyProperties(productPO, result);
        return result;
    }

    @Override
    public void checkProduct(Long costingProductId) {
        MaoriProductPO product = maoriProductMapper.selectById(costingProductId);
        if (!StringUtils.hasText(product.getPriceUnit())) {
            throw new BizException("售价单位 未填写");
        } else if (!StringUtils.hasText(product.getProductUnit())) {
            throw new BizException("产品长度单位 未填写");
        } else if (!StringUtils.hasText(product.getWeightUnit())) {
            throw new BizException("重量单位 未填写");
        } else if (null == product.getStoragePrice()) {
            throw new BizException("存储的价格 未填写");
        }
    }

    @Override
    public void updateProductStatus(Long productId, Integer status) {
        MaoriProductPO updateStatus = new MaoriProductPO();
        updateStatus.setId(productId);
        updateStatus.setStatus(status);
        maoriProductMapper.updateById(updateStatus);
    }
}
